package com.google.gwt.gfx.client.overlays;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.user.client.ui.Image;

/**
 * Cache of images for better performance.
 */
public class ImageFactory {

	public static final ImageFactory DEFAULT = new ImageFactory();

	private Map<String, Boolean> brokenUrlList = new HashMap<String, Boolean>();

	private Map<String, GFXImage> cache = new HashMap<String, GFXImage>();

	/**
	 * Clears all cache stored.
	 */
	public void clearCache() {
		cache.clear();
		brokenUrlList.clear();
	}

	/**
	 * @param url
	 *            URL of the image
	 * @return {@link #createImage(String, String)}
	 */
	public GFXImage createImage(final String url) {
		return createImage(url, url);
	}

	/**
	 * Gets a image overlay from this cache if key of the image is hit, or over
	 * network using URL of the image.Images fetched over network will be added
	 * to this cache.
	 * 
	 * @param key
	 *            identity of the image
	 * @param url
	 *            URL of the image
	 * @return an image from this cache or over network
	 */
	public GFXImage createImage(final String key, final String url) {
		if (cache.containsKey(key)) {
			return cache.get(key);
		} else {
			final GFXImage image = new GFXImage();
			image.addLoadHandler(new LoadHandler() {
				@Override
				public void onLoad(LoadEvent event) {
					if (brokenUrlList.containsKey(key)) {
						brokenUrlList.remove(key);
						return;
					}
					Image.prefetch(url);
					cache.put(key, image);
					image.style().setVisible(true);
				}
			});
			image.addErrorHandler(new ErrorHandler() {
				@Override
				public void onError(ErrorEvent event) {
					if (cache.containsKey(key)) {
						cache.remove(key);
					}
					brokenUrlList.put(key, true);
					image.setWidth("0px");
					image.setHeight("0px");
				}
			});
			image.style().setSelectable(false);
			image.setUrl(url);
			return image;
		}
	}

}
